package com.fingard.dsp.bank.directbank.alipay01;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePayRequest;
import com.alipay.api.response.AlipayTradePayResponse;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.bankInterface.IEntrustRec;
import com.fingard.dsp.bank.reqrespobj.entrust.ReqEntrustRec;
import com.fingard.dsp.bank.reqrespobj.entrust.ReqQueryEntrustRec;
import com.fingard.dsp.bank.reqrespobj.entrust.RetAtsEntrustRec;
import com.fingard.dsp.bank.reqrespobj.entrust.RetAtsQueryEntrustRec;
import com.fingard.text.StringHelper;
import net.sf.json.JSONObject;

import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

/**
 * 支付宝代扣接口(周期扣款)
 */
public class ALIPAY01EntrustRec extends ALIPAY01Base implements IEntrustRec {
    /**
     * 参考文档：https://opendocs.alipay.com/apis/api_1/alipay.trade.pay/
     * <p>
     * alipay.trade.pay(统一收单交易支付接口)
     * 收银员使用扫码设备读取用户手机支付宝“付款码”/声波获取设备（如麦克风）读取用户手机支付宝的声波信息后，将二维码或条码信息/声波信息通过本接口上送至支付宝发起支付。
     * <p>
     *
     * @param p_req
     * @return
     */
    @Override
    public RetAtsEntrustRec submitEntrustRec(ReqEntrustRec p_req) {
        RetAtsEntrustRec retAts = new RetAtsEntrustRec(p_req);

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req.ownAct, "unifiedorder");
            if (actItem != null) {
                JSONObject alipayJsonRequest = new JSONObject();

                alipayJsonRequest.put("out_trade_no", p_req.rdSeq);//商户订单号
                alipayJsonRequest.put("scene", "bar_code");//支付场景  条码支付，取值：bar_code  声波支付，取值：wave_code
                alipayJsonRequest.put("auth_code", p_req.channelAuthCode);//支付授权码
                alipayJsonRequest.put("product_code", "FACE_TO_FACE_PAYMENT");//销售产品码
                alipayJsonRequest.put("subject", p_req.description);//订单标题
                alipayJsonRequest.put("buyer_id", p_req.merchantId);//支付宝用户ID
                alipayJsonRequest.put("seller_id", p_req.merchantId);//支付宝用户ID
                alipayJsonRequest.put("total_amount", p_req.amount);//订单总金额
                alipayJsonRequest.put("trans_currency", convertCurToBank(p_req.cur));//标价币种
                alipayJsonRequest.put("settle_currency", convertCurToBank(p_req.cur));//商户指定的结算币种
                alipayJsonRequest.put("discountable_amount", "");//参与优惠计算的金额,单位为元
                alipayJsonRequest.put("body", p_req.attach);//订单描述

                JSONObject goods_detail = new JSONObject();
                goods_detail.put("goods_id", actItem.appId);//商品的编号
                goods_detail.put("goods_name", p_req.memo);//商品名称
                goods_detail.put("quantity", "1");//商品数量
                goods_detail.put("price", p_req.amount);//商品单价，单位为元
                goods_detail.put("goods_category", "");//商品类目
                goods_detail.put("categories_tree", "");//商品类目树
                goods_detail.put("body", "");//商品描述信息
                goods_detail.put("show_url", "");//商品的展示地址
                alipayJsonRequest.put("goods_detail", goods_detail);
                alipayJsonRequest.put("operator_id", bankFront.operator);//商户操作员编号
                alipayJsonRequest.put("store_id", "");//商户门店编号
                alipayJsonRequest.put("terminal_id", actItem.termId);//商户机具终端编号

                JSONObject extend_params = new JSONObject();
                extend_params.put("sys_service_provider_id", "");
                extend_params.put("industry_reflux_info", "");
                extend_params.put("card_type", "");
                alipayJsonRequest.put("extend_params", extend_params);

                alipayJsonRequest.put("timeout_express", "");
                alipayJsonRequest.put("auth_confirm_mode", "");
                alipayJsonRequest.put("terminal_params", "");

                JSONObject promo_params = new JSONObject();
                promo_params.put("actual_order_time", "");
                alipayJsonRequest.put("promo_params", promo_params);
                alipayJsonRequest.put("advance_payment_type", "");
                alipayJsonRequest.put("query_options", "");
                alipayJsonRequest.put("request_org_pid", "");
                alipayJsonRequest.put("is_async_pay", "");


                String bizContent = JSON.toJSONString(alipayJsonRequest);
                bizContent = bizContent.replaceAll("\\\\\\\\", "");

                AlipayTradePayRequest request = new AlipayTradePayRequest();
                TreeMap<String, String> signMapParams = new TreeMap<String, String>();

                signMapParams.put("app_id", actItem.appId);
                signMapParams.put("method", "alipay.trade.app.pay");
                signMapParams.put("format", "JSON");
                signMapParams.put("charset", getCharset());
                String signType = "RSA2";
                boolean useSignType = getBankConfig().getValueAsBool("useSignType");
                if (useSignType) {
                    signType = actItem.signType;
                }
                signMapParams.put("sign_type", signType);
                String timestamp = Format.DateTimeFormat.format(new Date());
                signMapParams.put("timestamp", timestamp);
                signMapParams.put("version", "1.0");
                signMapParams.put("notify_url", actItem.notifyURL);
                signMapParams.put("biz_content", bizContent);

                String mapStr = "";
                Iterator<Map.Entry<String, String>> it = signMapParams.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry<String, String> entry = it.next();
                    mapStr += entry.getKey() + ":" + entry.getValue() + "\r\n";
                }
                WriteBankLogLn("待签名MAP:\r\n" + mapStr);

                String signData = AlipaySignature.getSignContent(signMapParams);
                WriteBankLogLn2("待签名原始数据:" + signData);

                String signature = "";
                if ("RSA2".equalsIgnoreCase(signType)) {
                    signature = AlipaySignature.rsa256Sign(signData, actItem.ownKeyStorePath, getCharset());
                } else {
                    signature = AlipaySignature.rsaSign(signData, actItem.ownKeyStorePath, getCharset());
                }
                WriteBankLogLn2("本机生成签名:\r\n" + signature);
                signMapParams.put("sign", signature);
                request.setBizContent(convertMapToStr(signMapParams));
                AlipayClient alipayClient = new DefaultAlipayClient(bankFront.getUrl("tradePayApply"), actItem.appId,
                        actItem.ownKeyStorePath, "json", getCharset(), actItem.oppCertFilePath, signType);

                WriteBankLogStep2(request.getBizContent());
                AlipayTradePayResponse response = alipayClient.pageExecute(request);
                WriteBankLogStep3(response.getBody());

                if (response != null) {
                    retAts.respCode = "0";
                    retAts.respInfo = response.getMsg();
                    if ("10000".equals(response.getCode())) {
                        retAts.transState = "0";
                    } else {
                        retAts.transState = "1";
                        retAts.errCode = StringHelper.joinNotEmpty("+", response.getCode(), response.getSubCode());
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = response.getBody();
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "未找到账号:[" + p_req.ownAct + "]商户配置信息,请检查'config/portfiles/" + p_req.reqHeader.bankCode + "/config.xml'中该账号相关商户配置节点是否配置正确!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }
        return retAts;
    }

    @Override
    public RetAtsQueryEntrustRec queryEntrustRec(ReqQueryEntrustRec p_req) {
        return null;
    }
}
